<template>
  <div class="goods-sku">
    <dl v-for="item in goods.specs" :key="item.id">
      <dt>{{ item.name }}</dt>
      <dd>
        <template v-for="sub in item.values" :key="sub.name">
          <img
            v-if="sub.picture"
            :src="sub.picture"
            alt=""
            :title="sub.name"
            @click="changeSelected(item, sub)"
            :class="{ selected: sub.selected, disabled: sub.disabled }"
          />
          <span
            v-else
            @click="changeSelected(item, sub)"
            :class="{ selected: sub.selected, disabled: sub.disabled }"
            >{{ sub.name }}</span
          >
        </template>
      </dd>
    </dl>
  </div>
</template>

<script setup lang="ts" name="GoodsSku">
import { GoodsInfo, Spec, SpecValue } from '@/types/goods'
import bwPowerSet from '@/utils/power-set'
const props = defineProps<{
  goods: GoodsInfo
  skuId?: string
}>()
const emit = defineEmits<{
  (e: 'changeSku', skuId: string): void
}>()
const SPLIT_STR = '+'
// 商品规格选择逻辑
const changeSelected = (item: Spec, sub: SpecValue) => {
  if (sub.disabled) return // 如果禁用状态直接 return
  // 选中的状态
  if (sub.selected) {
    sub.selected = false
  } else {
    // 没有选择点击就高亮
    item.values.forEach((sub) => (sub.selected = false))
    sub.selected = true
  }
  // 一旦按钮被重新选择了，按钮状态也会随之需要更新
  updateDisabledStatus()

  const selectArr = getSelectedSpec()
  const len = selectArr.filter(Boolean).length
  if (len === props.goods.specs.length) {
    // 说明全部选中
    // 2. 去pathMap找到对应的skuid
    const skuId = pathMap[selectArr.join(SPLIT_STR)][0]
    // 3. 子传父，将skuid传递给父组件
    emit('changeSku', skuId)
  } else {
    emit('changeSku', '')
  }
}
// 获取选中的规格
const getSelectedSpec = () => {
  const arr: string[] = []
  props.goods.specs.forEach((item) => {
    const temp = item.values.find((sub) => sub.selected)
    arr.push(temp ? temp.name : '')
  })
  return arr
}
const pathMap: any = {}
// 获取路径字典
const getPathMap = () => {
  // 1. 过滤掉库存为0的sku
  const skus = props.goods.skus.filter((item) => item.inventory > 0)
  // 2. 遍历有效的sku,获取sku的幂集
  skus.forEach((item) => {
    const arr = item.specs.map((sub) => sub.valueName)
    // 3. 调用powerSet获取幂集
    const powerSet = bwPowerSet(arr)
    // 4. 把这些powerSet合并到一个路径字典中
    powerSet.forEach((sub) => {
      // 5. 判断pathMap中有没有key
      const key = sub.join(SPLIT_STR)
      if (key in pathMap) {
        // 6. 存在
        pathMap[key].push(item.id)
      } else {
        // 7. 不存在
        pathMap[key] = [item.id]
      }
    })
  })
  return pathMap
}
getPathMap()

// 更新按钮的禁用状态
const updateDisabledStatus = () => {
  const selectArr = getSelectedSpec()
  props.goods.specs.forEach((item, index) => {
    const tempArr = [...selectArr]
    item.values.forEach((sub) => {
      tempArr[index] = sub.name
      // 生成组合 key
      const key = tempArr.filter(Boolean).join(SPLIT_STR)
      if (key in pathMap) {
        // 当前规格的名字在pathMap存在，不禁用
        sub.disabled = false
      } else {
        // 当前规格在pathMap找不到，禁用
        sub.disabled = true
      }
    })
  })
}
updateDisabledStatus()

// 根据父传子，传递的skuId，进行回显，设置选中状态
const initSelected = () => {
  if (!props.skuId) return

  const sku = props.goods.skus.find((item) => item.id === props.skuId)

  if (!sku) return
  props.goods.specs.forEach((item, index) => {
    const text = sku.specs[index].valueName
    const specValue = item.values.find((sub) => sub.name === text)
    specValue!.selected = true
  })
}
initSelected()
</script>

<style scoped lang="less">
.sku-state-mixin () {
  border: 1px solid #e4e4e4;
  margin-right: 10px;
  cursor: pointer;

  &.selected {
    border-color: @xtxColor;
  }

  &.disabled {
    opacity: 0.6;
    border-style: dashed;
    cursor: not-allowed;
  }
}

.goods-sku {
  padding-left: 10px;
  padding-top: 20px;

  dl {
    display: flex;
    padding-bottom: 20px;
    align-items: center;

    dt {
      width: 50px;
      color: #999;
    }

    dd {
      flex: 1;
      color: #666;

      > img {
        width: 50px;
        height: 50px;
        margin-top: 5px;
        .sku-state-mixin ();
      }

      > span {
        display: inline-block;
        height: 30px;
        line-height: 30px;
        padding: 0 20px;
        margin-top: 5px;
        .sku-state-mixin ();
      }
    }
  }
}
</style>
